{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Caffe2 sub-imports\n",
    "\n",
    "The main sub-imports caffe2 has are:\n",
    "\n",
    "### 1) contrib\n",
    "\n",
    "### 2) proto\n",
    "\n",
    "### 3) python\n",
    "\n",
    "### 4) experiments.\n",
    "\n",
    "Of the above, in this course, we will cover proto, python and experiments"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Contrib\n",
    "\n",
    "Caffe2 Contrib handles the third party module itegrations. These integrated 3rd party modules are nccl, gloo, nervana-gpu, nnpack, tensorboard, torch, etc. The details on these 3rd party modules are present in the resource folder of section 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Proto\n",
    "\n",
    "Protobuf, or protocol buffer, is a json-like serialization tool for structured data. Caffe2 prototocol buffer messages are stored in this module. The values in it can be retrieved or modified, and then used be used with the caffe2's python and experiments modules.\n",
    "\n",
    "Operators in caffe2 are protobuf objects. Thus networks and associated network parameters too are protobuf objects.\n",
    "\n",
    "Below we create an Addition operator and see what type it is and it is structured"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:root:This caffe2 python run does not have GPU support. Will run in CPU only mode.\n",
      "WARNING:root:Debug message: No module named caffe2_pybind11_state_gpu\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Type of the created op is: <class 'caffe2.proto.caffe2_pb2.OperatorDef'>\n",
      "Content:\n",
      "\n",
      "input: \"X1\"\n",
      "input: \"X2\"\n",
      "output: \"Y\"\n",
      "name: \"sample\"\n",
      "type: \"Add\"\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from caffe2.python import core, workspace \n",
    "op = core.CreateOperator(\n",
    "    \"Add\",                                           # The type of operator that we want to run\n",
    "    [\"X1\", \"X2\"],                                    # Inputs\n",
    "    [\"Y\"],                                           # Output\n",
    "    name=\"sample\",\n",
    ")\n",
    "print(\"Type of the created op is: {}\".format(type(op)))\n",
    "print(\"Content:\\n\")\n",
    "print(str(op))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Thus the type of operator is **class 'caffe2.proto.caffe2_pb2.OperatorDef'**\n",
    "\n",
    "And the data is structured **input -> output -> name -> type -> parameters**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################################################################################################\n",
    "##################################################################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The folder to be considered when understanding these buffer values is <caffe2_root>/caffe2/proto/\n",
    "The most important file in this folder is caffe2.proto\n",
    "\n",
    "Of all the values present in this folder we are interested in\n",
    "\n",
    "### 1) DataType Enum -> Data type Enumerator\n",
    "\n",
    "### 2) DeviceType Enum -> Device type Enumerator\n",
    "\n",
    "### 3) DeviceOption -> Device Option"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################################################################################################\n",
    "##################################################################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DataType Enum\n",
    "\n",
    "Ref: https://github.com/caffe2/caffe2/blob/master/caffe2/proto/caffe2.proto\n",
    "enum DataType {\n",
    "\n",
    "    UNDEFINED = 0;\n",
    "    FLOAT = 1;  // float\n",
    "    INT32 = 2;  // int\n",
    "    BYTE = 3;  // BYTE, when deserialized, is going to be restored as uint8.\n",
    "    STRING = 4;  // string\n",
    "    // Less-commonly used data types.\n",
    "    BOOL = 5;  // bool\n",
    "    UINT8 = 6;  // uint8_t\n",
    "    INT8 = 7;  // int8_t\n",
    "    UINT16 = 8;  // uint16_t\n",
    "    INT16 = 9;  // int16_t\n",
    "    INT64 = 10;  // int64_t\n",
    "    FLOAT16 = 12;  // caffe2::float16\n",
    "    DOUBLE = 13;  // double\n",
    "    \n",
    "  }\n",
    "  \n",
    "While working with **tensor-data** type casting, loading input data into networks, and whenever the type of data has to be examined or specified, it can be **addressed with its key**. For example, 1 for float, 13 for double, etc.  \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################################################################################################\n",
    "##################################################################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DeviceType Enum and DeviceOption\n",
    "\n",
    "Ref: https://github.com/caffe2/caffe2/blob/master/caffe2/proto/caffe2.proto\n",
    "enum DeviceType {\n",
    "\n",
    "    CPU = 0;                    // In default, we will use CPU.\n",
    "    CUDA = 1;                   // CUDA.\n",
    "    MKLDNN = 2;                 // Reserved for explicit MKLDNN\n",
    "    OPENGL = 3;                 // OpenGL\n",
    "    // Change the following number if you add more devices in the code.\n",
    "    COMPILE_TIME_MAX_DEVICE_TYPES = 4;\n",
    "    ONLY_FOR_TEST = 20901701;   // This device type is only for test.\n",
    "\n",
    "}\n",
    "\n",
    "With deep learning, the flexibility to use the device to run the code is must. Caffe2 provides this feature using the DeviceType enumerator.\n",
    "\n",
    "Example: \n",
    "\n",
    "1) To run the code on CPU, keep the DeviceType option to 0\n",
    "\n",
    "2) To run it on cuda powered GPU. keep it to 1.\n",
    "\n",
    "\n",
    "Now, even after selecting which deployment platform (CPUs or GPUs) to use, sometimes it is required to share the resources between multiple GPUs or multiple CPU nodes. This can be done using **Device Option**\n",
    "\n",
    "Ref: https://github.com/caffe2/caffe2/blob/master/caffe2/proto/caffe2.proto\n",
    "message DeviceOption {\n",
    "\n",
    "    // [general] Options that need to be carried out before running the execution.\n",
    "    // optional DeviceType device_type = 1 [ default = CPU ];\n",
    "    optional int32 device_type = 1 [ default = 0 ]; // 0 is CPU.\n",
    "  \n",
    "    // [CUDA specific] the cuda gpu id.\n",
    "    optional int32 cuda_gpu_id = 2;\n",
    "    \n",
    "    // [general] The random seed to start the device random number generator with.\n",
    "    optional uint32 random_seed = 3;\n",
    "  \n",
    "    // [general] What node this op should execute on.\n",
    "    // Used for net transformation purposes. Must be empty at execution time.\n",
    "    optional string node_name = 4;\n",
    "}\n",
    "\n",
    "This, Device option can be accessed using the snippet mentioned below. It is currently commented as our deployment system does not have a GPU device."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nfrom caffe2.python import core, workspace \\nfrom caffe2.proto import caffe2_pb2             #Save layers as files\\n\\ndevice_option = caffe2_pb2.DeviceOption()\\ndevice_option.device_type = caffe2_pb2.CUDA\\ndevice_option.cuda_gpu_id = 2\\n\\nwith core.DeviceScope(device_option):\\n    # The network starts here\\n'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Example: If using the 2nd cuda enabled GPU\n",
    "'''\n",
    "from caffe2.python import core, workspace \n",
    "from caffe2.proto import caffe2_pb2             #Save layers as files\n",
    "\n",
    "device_option = caffe2_pb2.DeviceOption()\n",
    "device_option.device_type = caffe2_pb2.CUDA\n",
    "device_option.cuda_gpu_id = 2\n",
    "\n",
    "with core.DeviceScope(device_option):\n",
    "    # The network starts here\n",
    "'''   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Caffe2 Experiments\n",
    "\n",
    "Caffe2 has a set of pre-trained experiments and the one we are interested is **convnet bechmark**.\n",
    "\n",
    "This python script enables a benchmark test on a few convolutional networks written and executed in caffe on your local machine. There you may specify which CNNs to use, which base platform to perform the tests on, etc.\n",
    "\n",
    "**Note:**\n",
    "\n",
    "1) Need not look into the code specifics at this stage of the course.\n",
    "\n",
    "2) The CNNs which are present in this benchmark will be taken into account in the upcoming sections.\n",
    "\n",
    "3) This benchmark test experiment will be dealt again in later sections.  \n",
    "\n",
    "**usage**: \n",
    "{\n",
    "    \n",
    "           caffe2_convnet_benchmarks.py [-h] [--batch_size BATCH_SIZE]\n",
    "                                        [--model MODEL] [--order ORDER]\n",
    "                                        [--cudnn_ws CUDNN_WS]\n",
    "                                        [--iterations ITERATIONS]\n",
    "                                        [--warmup_iterations WARMUP_ITERATIONS]\n",
    "                                        [--forward_only] [--layer_wise_benchmark]\n",
    "                                        [--cpu] [--dump_model]\n",
    "                                        [--net_type NET_TYPE]\n",
    "                                        [--num_workers NUM_WORKERS]\n",
    "\n",
    "}\n",
    "\n",
    "1) model -> The available models are AlexNet, OverFeat , Inception, VGG\n",
    "\n",
    "2) cpu -> Use this to run the bechmark tests on cpu only\n",
    "\n",
    "3) forward_only -> Use this to disable backpropagation \n",
    "\n",
    "\n",
    "A sample output of the above code when run using the command on a **CPU** machine: \n",
    "*python caffe2_convnet_benchmarks.py --batch_size 32 --model AlexNet --forward_only --cpu*\n",
    "**is**:\n",
    "\n",
    "{\n",
    "\n",
    "    AlexNet: running forward only.\n",
    "    I0323 17:53:59.777555 23016 net_dag_utils.cc:118] Operator graph pruning prior to chain compute took: 1.2837e-05 secs\n",
    "    I0323 17:53:59.777628 23016 net_dag.cc:61] Number of parallel execution chains 1 Number of operators = 21\n",
    "    I0323 17:54:24.999790 23016 plan_executor.cc:498] Started executing plan.\n",
    "    I0323 17:54:24.999830 23016 plan_executor.cc:504] Initializing networks.\n",
    "    I0323 17:54:25.001013 23016 net_dag_utils.cc:118] Operator graph pruning prior to chain compute took: 1.2572e-05 secs\n",
    "    I0323 17:54:25.001073 23016 net_dag.cc:61] Number of parallel execution chains 1 Number of operators = 21\n",
    "    I0323 17:54:49.409679 23016 plan_executor.cc:527] Step run took 24.4098 seconds.\n",
    "    I0323 17:54:49.409771 23016 plan_executor.cc:538] Total plan took 24.4099 seconds.\n",
    "    I0323 17:54:49.409791 23016 plan_executor.cc:539] Plan executed successfully.\n",
    "    Spent: 2.4410340786\n",
    "}\n",
    "\n",
    "**Time Taken: 2.44 s**\n",
    "\n",
    "\n",
    "\n",
    "A sample output of the above code when run using the command on a **GPU** enabled machine: \n",
    "*python caffe2_convnet_benchmarks.py --batch_size 32 --model AlexNet --forward_only*\n",
    "**is**:\n",
    "\n",
    "{\n",
    "\n",
    "    AlexNet: running forward only.\n",
    "    I0323 19:17:46.928638  4748 net_dag_utils.cc:118] Operator graph pruning prior to chain compute took: 4.2709e-05 secs\n",
    "    I0323 19:17:46.936877  4748 net_dag.cc:61] Number of parallel execution chains 1 Number of operators = 21\n",
    "    I0323 19:17:50.824479  4748 plan_executor.cc:498] Started executing plan.\n",
    "    I0323 19:17:50.824496  4748 plan_executor.cc:504] Initializing networks.\n",
    "    I0323 19:17:50.826273  4748 net_dag_utils.cc:118] Operator graph pruning prior to chain compute took: 9.105e-06 secs\n",
    "    I0323 19:17:50.826303  4748 net_dag.cc:61] Number of parallel execution chains 1 Number of operators = 21\n",
    "    I0323 19:17:50.963599  4748 plan_executor.cc:527] Step run took 0.139076 seconds\n",
    "    I0323 19:17:50.963637  4748 plan_executor.cc:538] Total plan took 0.139135 seconds.\n",
    "    I0323 19:17:50.963641  4748 plan_executor.cc:539] Plan executed successfully.\n",
    "    Spent: 0.0139375925064\n",
    "}\n",
    "\n",
    "**Time taken: 0.0139375925064 s**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################\n",
    "##################################################################################################"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Caffe2 Python Module\n",
    "\n",
    "Will be explained in the next video"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
